/**
 * 作者: 会写BUG
 * 创作日期: 2025/3/21 13:57
 * 描述: cwbQtPractice.ChessPanel
 *
 **/
#include "chess_panel.h"
#include "score_record.h"

#include <QKeyEvent>
#include <QPainter>
#include <QPainterPath>

ChessPanel::ChessPanel(QWidget* _parent)
    : QWidget(_parent)
{
    setFocusPolicy(Qt::WheelFocus);
    initChessRect();
    installEventFilter(this);

}

ChessPanel::~ChessPanel()
{
    qDeleteAll(number_cheeses_);
}

QSize ChessPanel::sizeHint() const
{
    int width = chess_size_.width() * 4 + grid_space_ * 5;
    int height = chess_size_.height() * 4 + grid_space_ * 5;
    return {width, height};
}

void ChessPanel::initChessRect()
{
    int start_pos_x = 0, start_pos_y = 0;

    for (int row = 0; row < 4; ++row)
    {
        start_pos_y = row * chess_size_.height() + grid_space_ * (row + 1);
        for (int col = 0; col < 4; ++col)
        {
            start_pos_x = col * chess_size_.width() + grid_space_ * (col + 1);
            chess_rects_ << QRect(start_pos_x, start_pos_y, chess_size_.width(), chess_size_.height());
        }
    }

    move_animation_group_ = new QParallelAnimationGroup(this);
    connect(move_animation_group_, &QParallelAnimationGroup::finished, this, &ChessPanel::moveAnimationEnd);
}


QPoint ChessPanel::convertMatrixPos(int _index)
{
    if (_index < 0 || _index > 15)
    {
        return QPoint();
    }
    int row = _index / 4;
    int col = _index % 4;
    return QPoint(col, row);
}

int ChessPanel::convertIndex(int _row, int _col)
{
    if (_row < 0 || _row > 3 || _col < 0 || _col > 3)
    {
        return -1;
    }
    return _row * 4 + _col;
}

void ChessPanel::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.setPen(Qt::transparent);
    painter.setBrush(QColor(223, 203, 168));
    painter.drawRect(rect());

    painter.setBrush(QColor(215, 195, 162));
    for (int index = 0; index < chess_rects_.count(); ++index)
    {
        painter.drawRect(chess_rects_[index]);
    }


}

bool ChessPanel::eventFilter(QObject* watched, QEvent* event)
{
    if (watched != this)
        return false;

    else if (event->type() == QEvent::KeyRelease)
    {
        if (move_animation_group_->state() != QAbstractAnimation::Running)
        {
            move_animation_group_->clear();
            QKeyEvent* key_event = dynamic_cast<QKeyEvent*>(event);
            int move = 0;
            if (key_event->key() == Qt::Key_Up)
            {
                moveUp();
                move = 1;
            }
            else if (key_event->key() == Qt::Key_Down)
            {
                moveDown();
                move = 2;
            }
            else if (key_event->key() == Qt::Key_Left)
            {
                moveLeft();
                move = 3;
            }
            else if (key_event->key() == Qt::Key_Right)
            {
                moveRight();
                move = 4;
            }
            else {
                return QWidget::eventFilter(watched, event);
            }
#ifdef GAME_TEST
            move_direction_ = move;
#endif
            move_animation_group_->start();
        }

    }

    return QWidget::eventFilter(watched, event);
}

void ChessPanel::moveUp()
{
    NumberChess* last_chess = nullptr;

    for (int col = 0; col < 4; ++col)
    {
        last_chess = nullptr;
        for (int row = 0; row < 4; ++row)
        {
            /* 获取索引号 */
            int index = convertIndex(row, col);
            /* 获取当前棋子 */
            NumberChess* chess = number_cheeses_.value(index);
            if (chess == nullptr)
            {
                /* 当前格没有数字 */
                continue;
            }

            if (last_chess == nullptr)
            {
                /* 此列中还没有数字快，因此，当前这个 chess 要移动到当前列的第一行的位置 */
                int move_index = convertIndex(0, col);
                QRect move_rect = chess_rects_.value(move_index);
                move_animation_group_->addAnimation(chess->moveTo(move_rect));
                chess->setIndex(move_index);
            }
            else
            {
                if (chess->number() == last_chess->number() && !last_chess->needAdd())
                {
                    /* 数字相同，合并 */
                    QRect move_rect = chess_rects_.value(last_chess->index());
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(last_chess->index());
                    chess->setNeedAdd(true);
                    /* 设置动画结束后删除标志 */
                    last_chess->setNeedDelete(true);
                    /*chess->raise();
                    last_chess->lower();*/
                }
                else
                {
                    /* 数字不同，移动到上一个数字快的下面 */
                    int move_index = last_chess->index() + 4;
                    QRect move_rect = chess_rects_.value(move_index);
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(move_index);
                }
            }
            last_chess = chess;
        }
    }
}

void ChessPanel::moveDown()
{
    NumberChess* last_chess = nullptr;

    for (int col = 0; col < 4; ++col)
    {
        last_chess = nullptr;
        for (int row = 3; row >= 0; --row)
        {
            /* 获取索引号 */
            int index = convertIndex(row, col);
            /* 获取当前棋子 */
            NumberChess* chess = number_cheeses_.value(index);
            if (chess == nullptr)
            {
                /* 当前格没有数字 */
                continue;
            }

            if (last_chess == nullptr)
            {
                /* 此列中还没有数字快，因此，当前这个 chess 要移动到当前列的第四行的位置 */
                int move_index = convertIndex(3, col);
                QRect move_rect = chess_rects_.value(move_index);
                move_animation_group_->addAnimation(chess->moveTo(move_rect));
                chess->setIndex(move_index);
            }
            else
            {
                if (chess->number() == last_chess->number() && !last_chess->needAdd())
                {
                    /* 数字相同，合并 */
                    QRect move_rect = chess_rects_.value(last_chess->index());
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(last_chess->index());
                    chess->setNeedAdd(true);
                    /* 设置动画结束后删除标志 */
                    last_chess->setNeedDelete(true);
                    /*chess->raise();
                    last_chess->lower();*/
                }
                else
                {
                    /* 数字不同，移动到上一个数字快的上面 */
                    int move_index = last_chess->index() - 4;
                    QRect move_rect = chess_rects_.value(move_index);
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(move_index);
                }
            }
            last_chess = chess;
        }
    }
}

void ChessPanel::moveLeft()
{
    NumberChess* last_chess = nullptr;

    for (int row = 0; row < 4; ++row)
    {
        last_chess = nullptr;
        for (int col = 0; col < 4; ++col)
        {
            /* 获取索引号 */
            int index = convertIndex(row, col);
            /* 获取当前棋子 */
            NumberChess* chess = number_cheeses_.value(index);
            if (chess == nullptr)
            {
                /* 当前格没有数字 */
                continue;
            }

            if (last_chess == nullptr)
            {
                /* 此列中还没有数字快，因此，当前这个 chess 要移动到当前行的第一列的位置 */
                int move_index = convertIndex(row, 0);
                QRect move_rect = chess_rects_.value(move_index);
                move_animation_group_->addAnimation(chess->moveTo(move_rect));
                chess->setIndex(move_index);
            }
            else
            {
                if (chess->number() == last_chess->number() && !last_chess->needAdd())
                {
                    /* 数字相同，合并 */
                    QRect move_rect = chess_rects_.value(last_chess->index());
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(last_chess->index());
                    chess->setNeedAdd(true);
                    /* 设置动画结束后删除标志 */
                    last_chess->setNeedDelete(true);
                    /*chess->raise();
                    last_chess->lower();*/
                }
                else
                {
                    /* 数字不同，移动到上一个数字快的右面 */
                    int move_index = last_chess->index() + 1;
                    QRect move_rect = chess_rects_.value(move_index);
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(move_index);
                }
            }
            last_chess = chess;
        }
    }
}

void ChessPanel::moveRight()
{
    NumberChess* last_chess = nullptr;

    for (int row = 0; row < 4; ++row)
    {
        last_chess = nullptr;
        for (int col = 3; col >= 0; --col)
        {
            /* 获取索引号 */
            int index = convertIndex(row, col);
            /* 获取当前棋子 */
            NumberChess* chess = number_cheeses_.value(index);
            if (chess == nullptr)
            {
                /* 当前格没有数字 */
                continue;
            }

            if (last_chess == nullptr)
            {
                /* 此列中还没有数字快，因此，当前这个 chess 要移动到当前行的第四列的位置 */
                int move_index = convertIndex(row, 3);
                QRect move_rect = chess_rects_.value(move_index);
                move_animation_group_->addAnimation(chess->moveTo(move_rect));
                chess->setIndex(move_index);
            }
            else
            {
                if (chess->number() == last_chess->number() && !last_chess->needAdd())
                {
                    /* 数字相同，合并 */
                    QRect move_rect = chess_rects_.value(last_chess->index());
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(last_chess->index());
                    chess->setNeedAdd(true);
                    /* 设置动画结束后删除标志 */
                    last_chess->setNeedDelete(true);
                    /*chess->raise();
                    last_chess->lower();*/
                }
                else
                {
                    /* 数字不同，移动到上一个数字快的左面 */
                    int move_index = last_chess->index() - 1;
                    QRect move_rect = chess_rects_.value(move_index);
                    move_animation_group_->addAnimation(chess->moveTo(move_rect));
                    chess->setIndex(move_index);
                }
            }
            last_chess = chess;
        }
    }
}

void ChessPanel::updateChess()
{
    auto numbers = number_cheeses_.values();
    number_cheeses_.clear();
    SCORE_RECORD->resetChessNumber();
    /* 本次增加的分数 */
    int add_score = 0;
    for (int index = 0; index < numbers.count(); ++index)
    {
        NumberChess* chess = numbers[index];
        if (chess->needDelete())
        {
            /* 清除无效的数字块 */
            chess->deleteLater();
        }
        else
        {
            if (chess->needAdd())
            {
                chess->setNumber(chess->number() * 2);
                add_score += chess->number();
                chess->setNeedAdd(false);
            }
            number_cheeses_.insert(chess->index(), chess);
            SCORE_RECORD->setChessNumber(chess->index(), chess->number());
        }
    }

    int score = SCORE_RECORD->score();
    SCORE_RECORD->setScore(score + add_score);
    SCORE_RECORD->record();
}

void ChessPanel::moveAnimationEnd()
{
    /* 移动移动动画结束 */
    updateChess();
    /* 获取新的数字块位置 */
    QPair<int, int> pair = SCORE_RECORD->newChessPos();
    QPoint init_chess_pos = convertMatrixPos(pair.first);
    if (init_chess_pos.isNull()) {
        return;
    }
    NumberChess* number_chess = generateChess(init_chess_pos.y(), init_chess_pos.x(), pair.second);

    generate_animation_ = new QPropertyAnimation(number_chess, "geometry");
    generate_animation_->setDuration(100);
    QRect start_rect = number_chess->geometry();
    generate_animation_->setStartValue(QRect(start_rect.center().x() - 2, start_rect.center().y() - 2, 4, 4));
    generate_animation_->setEndValue(number_chess->geometry());

    connect(generate_animation_, &QPropertyAnimation::finished, this,
        [=, this]()
        {
            #ifdef GAME_TEST
            recordPanel(move_direction_);
            #endif
        });
    generate_animation_->start(QPropertyAnimation::DeleteWhenStopped);


}

NumberChess* ChessPanel::generateChess(int _row, int _col, int _num)
{
    int index = convertIndex(_row, _col);
    QRect chess_rect = chess_rects_.value(index);
    NumberChess* chess = new NumberChess(this, chess_rect);
    chess->setIndex(index);
    chess->setVisible(true);
    if (_num > 0)
    {
        chess->setNumber(_num);
    }
    number_cheeses_.insert(index, chess);

    return chess;
}

QSize ChessPanel::minimumSizeHint() const {
    return sizeHint();
}

void ChessPanel::loadChess()
{
    qDeleteAll(number_cheeses_);
    number_cheeses_.clear();

    auto chess_numbers = SCORE_RECORD->chessNumbers();

    for (int index = 0; index < chess_numbers.count(); ++index)
    {
        if (chess_numbers[index] == 0)
        {
            /* 没有数据 */
            continue;
        }
        QPoint pos = convertMatrixPos(index);
        generateChess(pos.y(), pos.x(), chess_numbers[index]);
    }
}

/*#ifdef GAME_TEST
void ChessPanel::recordPanel(int _move)
{
    QPixmap pixmap = grab();
    QString save_dir_path = qApp->applicationDirPath() + QDir::separator() + "/../records";
    /* 如果 save_dir_path 存在就是删除文件夹重新创建 #1#
    QDir save_dir(save_dir_path);
    QString save_file_path = save_dir_path + QDir::separator();
    if (_move == 0)
    {
        save_file_path += QString("%1_init.png").arg(record_index_++);
    }
    else if (_move == 1)
    {
        save_file_path += QString("%1_to_up.png").arg(record_index_++);
    }
    else if (_move == 2)
    {
        save_file_path += QString("%1_to_down.png").arg(record_index_++);
    }
    else if (_move == 3)
    {
        save_file_path += QString("%1_to_left.png").arg(record_index_++);
    }
    else if (_move == 4)
    {
        save_file_path += QString("%1_to_right.png").arg(record_index_++);
    }

    pixmap.save(save_file_path);
}
#endif*/